# -*- coding: UTF-8 -*-
'''
Created on 12.06.2014

@author: MathiasAr
'''

import pyexiv2, datetime, os, Image, StringIO, exceptions, time

from ImageTrim import imageTrim

def CanAutoOrient():
    p = os.popen("mogrify --version")
    p = p.readlines()
    for l in p:
        if "imagemagick" in l.lower():
            return True
        pass
    return False 

def GetImageTimeStamp(imageFile):
    try:
        md = pyexiv2.ImageMetadata(imageFile)
        if md != None:
            md.read()
            if 'Exif.Image.DateTime' in md:
                dt = md['Exif.Image.DateTime'].value
                return dt
    except:
        pass
    return datetime.datetime.fromtimestamp(os.path.getmtime(imageFile))

def SetImageTimeStamp(imageFile, timedelta=datetime.timedelta(0, 0)):
    dt = None
    if not type(timedelta) == datetime.timedelta:
        raise exceptions.TypeError("Argument timedelta must be instance of datetime.timedelta")
    try:
        md = pyexiv2.ImageMetadata(imageFile)
        if md != None:
            md.read()
            origDT = None
            for dtkey in ('Exif.Photo.DateTimeOriginal', 'Exif.Photo.DateTimeDigitized', 'Exif.Image.DateTime'):
                if dtkey in md:
                    dt = md[dtkey].value
                    if origDT == None:
                        origDT = dt
                    dt = origDT + timedelta
                    md[dtkey].value = dt
                    md.write(False)
    except:
        pass
    if dt == None:
        dt = datetime.datetime.fromtimestamp(os.path.getmtime(imageFile))
        dt += timedelta
    timestamp = time.mktime(dt.timetuple())
    os.utime(imageFile, (timestamp, timestamp))
    return dt

def GetImageOrientation(imageFile):
    try:
        md = pyexiv2.ImageMetadata(imageFile)
        if md != None:
            md.read()
            if 'Exif.Image.Orientation' in md:
                return md['Exif.Image.Orientation'].value
    except:
        pass
    return 0

def GetEXIF(imageFile):
    result = {}
    try:
        md = pyexiv2.ImageMetadata(imageFile)
        if md != None:
            md.read()
            for k in md:
                if not k or type(k) != str: continue
                if not k.startswith('Exif.Image.') and not k.startswith('Exif.Photo.'):
                    continue
                l = k.split('.')
                r = result
                n = 0
                for part in l:
                    n += 1
                    if n >= len(l):
                        r.setdefault(part, md[k].value)
                    elif not part in r:
                        r.setdefault(part, {})
                    r = r[part]
    except:
        pass
    return result

def SetEXIF(imageFile, key=['Exif'], value=None):
    try:
        md = pyexiv2.ImageMetadata(imageFile)
        if md != None:
            md.read()
            key = '.'.join(key)
            if key in md:
                md[key] = value
                md.write()
                return True
    except:
        pass
    return False

def AutoOrientImage(im, exifOrientValue):
    
    if exifOrientValue == 2:
        im = im.transpose(Image.FLIP_LEFT_RIGHT)
    if exifOrientValue == 4 or exifOrientValue == 5 or exifOrientValue == 7:
        im = im.transpose(Image.FLIP_TOP_BOTTOM)
    if exifOrientValue == 3:
        im = im.transpose(Image.ROTATE_180)
    if exifOrientValue == 5 or exifOrientValue == 8:
        im.transpose(Image.ROTATE_90)
    if exifOrientValue == 6 or exifOrientValue == 7:
        im = im.transpose(Image.ROTATE_270)
    return im

def GetOrAddKey(dict={}, key=None, new_value=None):
    if not key in dict:
        dict.setdefault(key, new_value)
    return dict[key]

def SetOrAddKey(dict={}, key=None, value=None):
    if not key in dict:
        dict.setdefault(key, value)
    else:
        dict[key] = value

def IsImageFile(fname):
    if not os.path.isfile(fname): return False
    fsplit = os.path.splitext(fname)
    fext = fsplit[-1].lower()[1:]  # lower and remove dot
    if fext in ['jpg', 'jpeg', 'bmp', 'gif', 'png', 'ico', 'gif', 'tif']:
        return True
    return False

def GroupImagesByCamera(files=[]):
    '''GroupImagesByCamera() --> return tuple ( {model: files [] }, {file: model} ) with
        first entry: a dictionary with model as key and file list as value and
        second entry: a dictionary with file as key and model as value.  
    Group images with same EXIF camera device model. Ignore all files without EXIF tag Exif.Image.Make and without Exif.Image.Model.
    '''
    result1 = {}  # camera make and model and files
    result2 = {}  # file and model
    for f in files:
        if IsImageFile(f):
            exinfo = GetEXIF(f)
            try:
                make = exinfo['Exif']['Image']['Make']
                model = exinfo['Exif']['Image']['Model']
                model = '/'.join((make, model))
                # model
                res1_val = GetOrAddKey(result1, model, [])
                res1_val.append(f)
                # file
                result2.setdefault(f, model)
            except:
                # no matching EXIF tags
                continue
    return (result1, result2)


def CropResize(im, targetSize):
    if targetSize[1] == 0: return im
    targetRatio = float(targetSize[0]) / float(targetSize[1]);
    
    # crop image to the target ratio
    srcX = float(im.size[0])
    srcY = float(im.size[1])
    sourceRatio = srcX / srcY;
    
    if (sourceRatio >= targetRatio):
        yCrop = srcY
        xCrop = srcY * targetRatio
    else:
        xCrop = srcX
        yCrop = srcX / targetRatio
        pass
    
    left = int((srcX - xCrop) / 2)
    right = int(srcX) - left
    upper = int((srcY - yCrop) / 2)
    lower = int(srcY) - upper
    
    im = im.crop((left, upper, right, lower))
    im = im.resize(targetSize, Image.ANTIALIAS)
    
    return im


def FitResize(im, targetSize):
    if targetSize[1] == 0 or im.size[1] == 0: return im
    
    # calculate ratio
    sourceRatio = float(im.size[0]) / float(im.size[1])
    targetRatio = float(targetSize[0]) / float(targetSize[1])
    
    # new image
    targetIm = Image.new('RGBA', targetSize, (0, 0, 0, 0))
    
    # Calculate X and Y size
    newSizeX = targetIm.size[0]
    newSizeY = targetIm.size[1]
    posX = 0
    posY = 0
    if sourceRatio > targetRatio:
        newSizeY = int(float(newSizeX) / sourceRatio)
        posY = (targetIm.size[1] - newSizeY) / 2
    elif sourceRatio < targetRatio:
        newSizeX = int(float(newSizeY) * sourceRatio)
        posX = (targetIm.size[0] - newSizeX) / 2
        pass
    # resize the source image
    im = im.resize((newSizeX, newSizeY))
    
    # calculate position in target image
    targetIm.paste(im, (posX, posY))
     
    return targetIm


def GtkColorToRGB(gtkColor):
    r = gtkColor.red
    g = gtkColor.green
    b = gtkColor.blue
    if (r > 0xff): r = (r & 0xff00) / 0x100
    if (g > 0xff): g = (g & 0xff00) / 0x100
    if (b > 0xff): b = (b & 0xff00) / 0x100
    return (r, g, b)

def isRGBImage(im):
    bands = im.getbands()
    if ("R" in bands and "G" in bands and "B" in bands):
        return True
    return False

def hasAlpha(im):
    return "A" in im.getbands()

try:
    import pygtk
    import gtk
    import gtk.glade

except:
    print "Couldn't import GTK package"

def GetGtkPixbuf(im):
    if isRGBImage(im):
        if hasAlpha(im):
            # remove alpha channel
            im = imageTrim(im, None, 0)
    else:
        im = im.convert("RGB")
    file1 = StringIO.StringIO()
    im.save(file1, "ppm")
    contents = file1.getvalue()
    file1.close()
    loader = gtk.gdk.PixbufLoader("pnm")
    loader.write(contents, len(contents))  
    pixbuf = loader.get_pixbuf()
    loader.close()
    return pixbuf
    


if __name__ == '__main__':
    # path = r'C:\Users\Public\Pictures\Sample Pictures'
    path = r'C:\Users\MathiasAr\Pictures\DCIM'
    imfiles = []
    for f in os.listdir(path):
        f = os.path.join(path, f)
        imfiles.append(f)
        pass

    GroupImagesByCamera(imfiles)

